#include "Part.h"
#include "__regs_base.h"
#include "debug.h"
#include "Mcu.h"
#include "Port.h"
#include "Ea.h"
#include "Eep.h"
#include "Mcal_Delay.h"
#include "Mcal_MemLibc.h"

#define EEP_MAX_EXE_TIMES       (10000u)
#define EEP_PREINIT_DELAY_US    (10000u)
#define EEP_REG_OFFSET          (0x800u)
#define EEP_REG_WIDTH           (1u)

static MemIf_JobResultType ea_eep_wait_mainfunction(void)
{
	MemIf_JobResultType job_result = MEMIF_JOB_FAILED;
	static uint16 max_times = EEP_MAX_EXE_TIMES;

	while (max_times > 0u) {
		Ea_MainFunction();
		Eep_MainFunction();

		job_result = Ea_GetJobResult();

		if (MEMIF_JOB_OK == job_result) {
			return E_OK;
		} else if (MEMIF_JOB_PENDING == job_result) {
		} else {
			return job_result;
		}
		max_times--;
	}
	return job_result;
}

void ea_set_mode(uint8 mode)
{
	Ea_SetMode(mode);
}

uint8 ea_read(uint16 block_number, uint16 block_offset, uint8 *data_buffer_ptr, uint16 length)
{
	return Ea_Read(block_number, block_offset, data_buffer_ptr, length);
}

uint8 ea_write(uint16 block_number, const uint8 *data_buffer_ptr)
{
	return Ea_Write(block_number, data_buffer_ptr);
}

void ea_cancel(void)
{
	Ea_Cancel();
}

uint8 ea_get_status(void)
{
	return Ea_GetStatus();
}

uint8 ea_get_job_result(void)
{
	return Ea_GetJobResult();
}

uint8 ea_invalidate_block(uint16 block_number)
{
	return Ea_InvalidateBlock(block_number);
}

uint8 ea_erase_immediate_block(uint16 block_number)
{
	return Ea_EraseImmediateBlock(block_number);
}

void ea_main_function(void)
{
	Ea_MainFunction();
}

void eep_main_function(void)
{
	Eep_MainFunction();
}

static void eep_preinit(void)
{
	const Mcu_ResetSigType *mram_rst_sigs[] = { &rstsig_mram1, &rstsig_mram2, &rstsig_mram3, &rstsig_mram4,
						    &rstsig_mram5 };

	for (uint32 i = 0; i < EEP_CFG_HOST_MAX_NUM; i++) {
		Mcu_Ip_ResetCtlAssert(mram_rst_sigs[Eep_ConfigData.controllerConfig[i].deviceId]);
		RMWREG32(APB_PMU_CORE_BASE + EEP_REG_OFFSET, Eep_ConfigData.controllerConfig[i].deviceId, EEP_REG_WIDTH,
			 !!Eep_ConfigData.controllerConfig[i].hostConfig.config.initialMode);
		Mcal_udelay(EEP_PREINIT_DELAY_US);
		Mcu_Ip_ResetCtlDeassert(mram_rst_sigs[Eep_ConfigData.controllerConfig[i].deviceId]);
	}
}

uint8 ea_eep_init(void)
{
	uint8 ret = 0;
	static uint16 max_times = EEP_MAX_EXE_TIMES;

	if (Eep_GetStatus() == MEMIF_UNINIT) {
		eep_preinit();
		Eep_Init(&Eep_ConfigData);
	}

	if (MEMIF_UNINIT == Eep_GetStatus()) {
		return E_NOT_OK;
	}

	MemIf_JobResultType job_result = MEMIF_JOB_FAILED;
	MemIf_StatusType mode_status = MEMIF_UNINIT;

	Ea_Init(NULL);

	while (max_times > 0) {
		Ea_MainFunction();
		Eep_MainFunction();

		mode_status = Ea_GetStatus();

		if (MEMIF_IDLE == mode_status) {
			ret = 0;
			break;
		} else if (MEMIF_BUSY_INTERNAL == mode_status) {
		} else {
			ret = E_NOT_OK;
			break;
		}
		max_times--;
	}

	job_result = Ea_GetJobResult();

	if (MEMIF_JOB_OK != job_result) {
		ret = E_NOT_OK;
	}

	return ret;
}

uint8 ea_write_block(uint16 block_number, uint8 *buffer_ptr)
{
	uint8 ret = 0;

	ret = Ea_Write(block_number, buffer_ptr);

	if (E_OK != ret) {
		return ret;
	}
	MemIf_JobResultType job_result = ea_eep_wait_mainfunction();
	return job_result;
}

uint8 ea_read_block(uint16 block_number, uint16 block_offset, uint8 *buffer_ptr, uint16 length)
{
	uint8 ret = E_NOT_OK;

	ret = Ea_Read(block_number, block_offset, buffer_ptr, length);

	if (E_OK != ret) {
		return ret;
	}
	MemIf_JobResultType job_result = ea_eep_wait_mainfunction();
	return job_result;
}
